#version 440

layout (binding = 0) uniform usampler2D gbuf0;
layout (binding = 1) uniform sampler2D gbuf1;

uniform vec3 lightVec[50];
uniform vec3 lightColor[50];

uniform int numLights = 50;

out vec4 FragColor;


struct fragmentInfo
{
   vec3 color;
   vec3 normal;
   float shiness;
   vec3 ws_coord;
};

void unpackGbuffer (vec2 coord, out fragmentInfo frag)
{
   uvec4 data0 = texelFetch (gbuf0, ivec2 (coord), 0);
   vec4 data1 = texelFetch (gbuf1, ivec2 (coord), 0);
   vec2 tmp;

   tmp = unpackHalf2x16 (data0.y);
   frag.color = vec3 (unpackHalf2x16 (data0.x), tmp.x);
   frag.normal = normalize (vec3 (tmp.y, unpackHalf2x16 (data0.z)));
   frag.ws_coord = data1.xyz;
}

vec4 light_fragment (fragmentInfo frag)
{
   int i;
   vec4 result = vec4 (0.0, 0.0, 0.0, 1.0);

   for (i = 0; i < numLights; i++) {      
      vec3 vV = normalize(-frag.ws_coord);
      //vec3 vL = (lsPos.xyz - frag.ws_coord);      
      vec3 vL = (lightVec[i].xyz - frag.ws_coord);      
      float dist = length (vL);      
      vL = normalize (vL);
      
      vec3 vN = normalize (frag.normal);
      
      float attenuation = 50.0 / (pow (dist, 4.0));     
      //attenuation = .0;
      // Diffuse
      float diffDot = max (0.0, dot (vL, vN));
      vec3 diffColor = (lightColor[i].rgb*diffDot)*frag.color;
      result.rgb += diffColor*attenuation;
      
      vec3 vR = normalize(reflect (-vL, vN));

      //attenuation*=10.0;
      attenuation = 50.0 / (pow (dist, 2.0));

      // Specular
      if(diffDot > 0) {
         float specDot = max (0.0, dot (vV, vR));
         float specPower = pow (specDot, 50.0);
         vec3 specColor = vec3(specPower);
         result.rgb += specColor*lightColor[i].rgb*attenuation;
      }      
   }
   return result;
}

void main (void)
{
   fragmentInfo frag;
   unpackGbuffer (vec2(gl_FragCoord.xy), frag);
   FragColor = light_fragment (frag);
   //FragColor = vec4(1.0,0.0,0.0,1.0);
}